#include <CL/cl.hpp>
#include <fstream>
#include <iostream>
#include <time.h>
#include "init_opencl.hpp"
#include "matrix_operations.hpp"
#include <math.h>

using namespace std;

float * atomicTest(OpenCLEnv openCLEnv, int nrTimes) {
	clock_t init, final;

	float * answer = new float[10];

	cl::Context context = openCLEnv.getContext();
	cl::CommandQueue queue = openCLEnv.getQueue();

	// Read source file
	ifstream sourceFile("atomic_test.cl");
	string sourceCode(
		istreambuf_iterator<char>(sourceFile),
		(istreambuf_iterator<char>()));
	cl::Program::Sources source(1, make_pair(sourceCode.c_str(), sourceCode.length()+1));

	// Make program of the source code in the context
	cl::Program program = cl::Program(context, source);

	// Build program for these specific devices
	program.build(openCLEnv.getDevices());

	// Make kernel
	cl::Kernel kernel(program, "atomic_test");

	cl::Buffer bufferAnswer = cl::Buffer(context, CL_MEM_WRITE_ONLY, 10 * sizeof(float));

	kernel.setArg(0, bufferAnswer);


	cl::NDRange global(1000);
	cl::NDRange local(1);

	init=clock();
	for(int i = 0; i < nrTimes; i++) {
		queue.enqueueNDRangeKernel(kernel, cl::NullRange, global, local);
		queue.enqueueReadBuffer(bufferAnswer, CL_TRUE, 0, 10 * sizeof(float), answer);
	}
	final=clock()-init;

	double time = (double)final / ((double)CLOCKS_PER_SEC);
	cout << "Calculation took: " << time << " seconds. (atomic test, running kernel)" << endl;

	cout << "atomic test, time per: " << time/nrTimes << endl;

	return answer;
}
